package com.yn.pet.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yn.pet.bus.dao.GenFenceAlarmDao;
import com.yn.pet.bus.entity.*;
import com.yn.pet.bus.enums.FenceTypeEnum;
import com.yn.pet.web.service.AlarmRecordService;
import com.yn.pet.web.service.DeviceSyncSettingsService;
import com.yn.pet.web.service.GenFenceAlarmService;
import com.yn.pet.web.service.GenFenceService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 地理围栏告警记录表(GenFenceAlarm)表服务实现类
 *
 * @author makejava
 * @since 2025-07-09 12:00:47
 */
@AllArgsConstructor
@Service("genFenceAlarmService")
public class GenFenceAlarmServiceImpl extends ServiceImpl<GenFenceAlarmDao, GenFenceAlarm> implements GenFenceAlarmService {

    private final GenFenceService genFenceService;
    private final DeviceSyncSettingsService deviceSyncSettingsService;
    private final AlarmRecordService alarmRecordService;

    @Override
    @Transactional
    public void addFenceAlarm(Long deviceId, List<LocationRealtime> locationRealtimeList) {
        List<GenFence> list = genFenceService.list(new LambdaQueryWrapper<GenFence>().eq(GenFence::getDeviceId, deviceId));
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        DeviceSyncSettings deviceSyncSettings = deviceSyncSettingsService.list(new LambdaQueryWrapper<DeviceSyncSettings>().eq(DeviceSyncSettings::getDeviceId, deviceId)).stream().findAny().orElse(null);
        if (deviceSyncSettings == null) {
            return;
        }
        Integer fenceEnabled = deviceSyncSettings.getFenceEnabled();
        Integer lowBatteryEnabled = deviceSyncSettings.getLowBatteryEnabled();
        List<GenFenceAlarm> genFenceAlarmList = new ArrayList<>();
        List<AlarmRecord> alarmRecordList = new ArrayList<>();
        for (GenFence genFence : list) {
            Integer useStatus = genFence.getUseStatus();
            if (Objects.equals(useStatus, 0)) {
                continue;
            }
            Integer isDelete = genFence.getIsDelete();
            if (Objects.equals(isDelete, 1)) {
                continue;
            }

            for (LocationRealtime locationRealtime : locationRealtimeList) {
                if (Objects.equals(lowBatteryEnabled, 1) && Objects.equals(locationRealtime.getBatteryAlarm(), 1)) {
                    AlarmRecord alarmRecord = new AlarmRecord();
                    alarmRecord.setDeviceId(deviceId);
                    alarmRecord.setLocationId(locationRealtime.getLocationId());
                    alarmRecord.setType(3);
                    alarmRecord.setCreateTime(new Date());
                    alarmRecord.setUpdateTime(new Date());
                    alarmRecord.setIsDelete(0);
                    alarmRecordList.add(alarmRecord);
                }

                if (Objects.equals(fenceEnabled, 0)) {
                    continue;
                }

                Integer fenceType = genFence.getFenceType();
                if (Objects.equals(fenceType, FenceTypeEnum.CIRCLE.getCode())) {
                    Double centerLat = genFence.getCenterLat();
                    Double centerLng = genFence.getCenterLng();
                    Integer radius = genFence.getRadius();
                    double[] point = new double[]{locationRealtime.getLongitude(), locationRealtime.getLatitude()};
                    double[] center = new double[]{centerLng, centerLat};
                    boolean inCircle = this.isPointInCircle(point, center, radius);
                    int alarmType = 2;
                    if (inCircle) {
                        alarmType = 1;
                    }

                    GenFenceAlarm genFenceAlarm = new GenFenceAlarm();
                    genFenceAlarm.setFenceId(genFence.getFenceId());
                    genFenceAlarm.setDeviceId(deviceId);
                    genFenceAlarm.setAlarmType(alarmType);
                    genFenceAlarm.setAlarmTime(new Date());
                    genFenceAlarm.setLocationId(locationRealtime.getLocationId());
                    genFenceAlarm.setProcessed(0);
                    genFenceAlarmList.add(genFenceAlarm);
                }
            }
        }
        if (!CollectionUtils.isEmpty(genFenceAlarmList)) {
            this.saveBatch(genFenceAlarmList);
        }
        if (!CollectionUtils.isEmpty(alarmRecordList)) {
            alarmRecordService.saveBatch(alarmRecordList);
        }

    }


    /**
     * 判断点是否在圆形区域内
     *
     * @param point  要判断的点 [经度, 纬度]
     * @param center 圆心 [经度, 纬度]
     * @param radius 半径（米）
     * @return true-在内部，false-在外部
     */
    public boolean isPointInCircle(double[] point, double[] center, double radius) {
        double distance = calculateDistance(point[0], point[1], center[0], center[1]);
        return distance <= radius;
    }

    /**
     * 计算两个经纬度坐标之间的距离（米）
     * 使用Haversine公式
     */
    private double calculateDistance(double lon1, double lat1, double lon2, double lat2) {
        final int R = 6371; // 地球半径（千米）

        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);

        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);

        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        // 转换为米
        return R * c * 1000;
    }
}

